`include "PRV564Config.v"
`include "PRV564Define.v"
//////////////////////////////////////////////////////////////////////////////////////////////////
//  Date    : 2021                                                                              //
//  Author  : Jack.Pan                                                                          //
//  Desc    : Instruction Front for PRV564 processor, include a ATU and I-Cache                 //
//  Version : 2.0(2ed updata Verision, BTB now avilible!)                                       //
//   "We choose to go to the moon, not because they are easy, but because they are hard"        //
//////////////////////////////////////////////////////////////////////////////////////////////////
module InstrFront
#(parameter ITLB_FIBID=8'h01)
(
//----------------------Global Signal in-----------------------
    input  wire              IFi_CLK,
    input  wire              IFi_ARST,
//-----------------------Flush and Branch----------------------
    input  wire              IFi_GFlush,            //Global Flush
    input  wire [`XLEN-1:0]  IFi_GPC,
    input  wire              IFi_BFlush,            //Branch Flush
    input  wire [`XLEN-1:0]  IFi_BPC,
//-----------------------TLB and Cache refersh----------------
    input  wire              IFi_fencevma,
    input  wire              IFi_fencei,
//-----------------------CSR value in--------------------------
    input   wire [43:0]       CSR_satpppn,
    input   wire [3:0]        CSR_satpmode,
    input   wire [1:0]        CSR_priv,
    input   wire              CSR_InhibitIcache,    
    input   wire              CSR_mxr,
    input   wire              CSR_sum,
//-----------------------BTB write port------------------------
    input  wire               BTB_wr_req,
    input  wire [`XLEN-1:0]   BTB_wr_PC,
    input  wire [`XLEN-1:0]   BTB_wr_predicted_PC,
    input  wire               BTB_wr_predicted_state_bit,
//-----------------------To ID stage----------------------------
    output  wire              PIP_IFo_MSC_valid,
    output  wire [`XLEN-1:0]  PIP_IFo_DATA_instr,
    output  wire [`XLEN-1:0]  PIP_IFo_INFO_pc,
    output  wire [`XLEN-1:0]  PIP_IFo_INFO_predictedPC,
    output  wire [1:0]        PIP_IFo_INFO_priv,
    output  wire              PIP_IFo_MSC_InstPageFlt,
    output  wire              PIP_IFo_MSC_InstAccFle,
    output  wire              PIP_IFo_MSC_InstAddrMis,
    input   wire              PIP_IFi_FC_ready,     //next stage is ready to go!
//--------------------FIB1--------------------------
    output  wire              ITLB_FIBo_WREN,        //write to FIB0 enable
    output  wire              ITLB_FIBo_REQ,         //request FIB0 trans
    input   wire              ITLB_FIBi_ACK,         //request acknowledge
    input   wire              ITLB_FIBi_FULL,        //FIB0 FIFO full
    output  wire [7:0]        ITLB_FIBo_ID,
    output  wire [7:0]        ITLB_FIBo_CMD,
    output  wire [3:0]        ITLB_FIBo_BURST,
    output  wire [3:0]        ITLB_FIBo_SIZE,
    output  wire [`XLEN-1:0]  ITLB_FIBo_ADDR,      
    output  wire [`XLEN-1:0]  ITLB_FIBo_DATA,
    input   wire [7:0]        ITLB_FIBi_ID,
    input   wire [7:0]        ITLB_FIBi_RPL,
    input   wire              ITLB_FIBi_V,
    input   wire [`XLEN-1:0]  ITLB_FIBi_DATA,
//------------------------Cache port--------------------
    output wire               IFo_AQ_V,          //add a new access to Access Queue
    output wire [7:0]         IFo_AQ_ID,         //new access's ID
    output wire [7:0]         IFo_AQ_CMD,        //command and
    output wire               IFo_AQ_CI,         //cache is inhibit
    output wire               IFo_AQ_WT,         //write through is needed
    output wire [15:0]        IFo_AQ_BSEL,       //Byte select
    output wire [127:0]       IFo_AQ_WDATA,      //write data (or exchange data)
    output wire [`XLEN-1:0]   IFo_AQ_ADDR,
    input wire                IFi_AQ_FULL,
    input wire                IFi_RQ_V,
    input wire [7:0]          IFi_RQ_ID,
    input wire                IFi_RQ_WRERR,
    input wire                IFi_RQ_RDERR,
    input wire                IFi_RQ_RDY,
    input wire [127:0]        IFi_RQ_RDATA,
    output wire               IFo_RQ_ACK
);
//-------------------------BTB-----------------------------
    wire [`XLEN-1:0]   BTBo_predicted_PC;
	wire [1:0]         BTBo_predicted;
//--------------------------ATU input------------------------
    wire               PIP_ATUi_MSC_valid;
    wire [`XLEN-1:0]   PIP_ATUi_DATA_VA,    PIP_ATUi_DATA_predictedPC;
    wire               PIP_ATUo_FC_ready;
//---------------------ATU connect to Access Table-------------
//                   [  write port  ]       [ read port ]
    wire              Tablei_WREN,          Tablei_RDEN;
    wire [7:0]        Tablei_WID,           Tablei_RID;
    wire                                    Tablei_Remove;
    wire                                    Tableo_V;
    wire [`XLEN-1:0]  Tablei_ADDR,          Tableo_ADDR;
    wire [`XLEN-1:0]  Tablei_PC,            Tableo_PC;
    wire [7:0]        Tablei_ITAG,          Tableo_ITAG;
    wire [1:0]        Tablei_priv,          Tableo_priv;
    wire [7:0]        Tablei_opcode,        Tableo_opcode;
    wire [1:0]        Tablei_opinfo,        Tableo_opinfo;
    wire [3:0]        Tablei_opsize,        Tableo_opsize;
    wire              Tablei_InstPageFlt,   Tableo_InstPageFlt;
    wire              Tablei_InstAddrMis,   Tableo_InstAddrmis;
    wire              Tablei_LoadPageFlt,   Tableo_LoadPageFlt;
    wire              Tablei_LoadAddrMis,   Tableo_LoadAddrMis;
    wire              Tablei_StorePageFlt,  Tableo_StorePageFlt;
    wire              Tablei_StoreAddreMis, Tableo_StoreAddrMis;
    wire              Tableo_FULL;
//---------------------------------BTB----------------------------------
BTB                         BTB(
//-------------------Global SIgnal----------------
    .clk                    (IFi_CLK), 
    .rst                    (IFi_ARST | IFi_fencei | IFi_fencevma),
//------------------read port1---------------------
    .rd_PC                  (PIP_ATUi_DATA_VA),
    .rd_predicted           (BTBo_predicted),
    .rd_predicted_PC        (BTBo_predicted_PC),
//----------------IDU write and check port--------
    .wr_req                 (BTB_wr_req),
    .wr_PC                  (BTB_wr_PC),
    .wr_predicted_PC        (BTB_wr_predicted_PC),
    .wr_predicted_state_bit (BTB_wr_predicted_state_bit)
);
//---------------------------------PC-----------------------------------
PC                          PC(
    .CLKi                   (IFi_CLK),
    .ARSTi                  (IFi_ARST),
    .B_newPC                (IFi_BPC),
    .G_newPC                (IFi_GPC),
    .B_flush                (IFi_BFlush),
    .G_flush                (IFi_GFlush),
    .BTB_predicted          (BTBo_predicted[1]),
    .BTB_predictedPC        (BTBo_predicted_PC),
    .PC_Val                 (PIP_ATUi_DATA_VA),
    .PC_valid               (PIP_ATUi_MSC_valid),
    .PCnext_predicted       (PIP_ATUi_DATA_predictedPC),
    .Ready                  (PIP_ATUo_FC_ready)
);
//------------------------------ATU---------------------------------------
ATU#(
    .FIB_ID             (ITLB_FIBID),
    .TLB_entry_NUM      (`ITLB_entry_NUM),
    .InstrATU           (1)                         //This is used as instruction front
) inst_ATU(
    .ATUi_CLK                       (IFi_CLK),
    .ATUi_ARST                      (IFi_ARST),
    .ATUi_Flush                     (IFi_BFlush | IFi_GFlush),
    .ATUi_ModifyPermit              (1'b1),
    .ATUi_ModifyPermitID            (8'h00),
    .ATUi_TLBrefersh                (IFi_fencevma),
    .ATUi_CacheRefersh              (IFi_fencei),
    .ATUi_CSR_CacheInhibit          (CSR_InhibitIcache),
    .ATUi_CSR_CacheWT               (1'b0),                 //I-Cache dont need write through mode
    .ATUi_CSR_mxr                   (CSR_mxr),
    .ATUi_CSR_sum                   (CSR_sum),
    .ATUi_CSR_satpmode              (CSR_satpmode),
    .ATUi_CSR_satpppn               (CSR_satpppn),
    .PIP_ATUi_MSC_valid             (PIP_ATUi_MSC_valid),
    .PIP_ATUi_Opcode                (`LSU_eXecute),
    .PIP_ATUi_OpInfo                (`Sign64),
    .PIP_ATUi_OpSize                (4'h4),
    .PIP_ATUi_INFO_ITAG             (8'h00),
    .PIP_ATUi_INFO_priv             (CSR_priv),
    .PIP_ATUi_INFO_unpage           (1'b0),
    .PIP_ATUi_INFO_PC               (PIP_ATUi_DATA_VA),             //指令地址转换时，VA和PC是一致的
    .PIP_ATUi_DATA_VA               (PIP_ATUi_DATA_VA),
    .PIP_ATUi_DATA_ds2              (PIP_ATUi_DATA_predictedPC),    //ds2用于传递指令前端预测的跳转地址
    .PIP_ATUo_FC_ready              (PIP_ATUo_FC_ready),
//------------------write to access table-----------------
    .Tablei_WREN                    (Tablei_WREN),
    .Tablei_WID                     (Tablei_WID),
    .Tablei_ADDR                    (Tablei_ADDR),
    .Tablei_PC                      (Tablei_PC),
    .Tablei_ITAG                    (Tablei_ITAG),
    .Tablei_priv                    (Tablei_priv),
    .Tablei_opcode                  (Tablei_opcode),
    .Tablei_opinfo                  (Tablei_opinfo),
    .Tablei_opsize                  (Tablei_opsize),
    .Tablei_ci                      (),                             //指令前端不需要记录当前访问为mmio类
    .Tablei_InstPageFlt             (Tablei_InstPageFlt),
    .Tablei_InstAddrMis             (Tablei_InstAddrMis),
    .Tablei_LoadPageFlt             (Tablei_LoadPageFlt),
    .Tablei_LoadAddrMis             (Tablei_LoadAddrMis),
    .Tablei_StorePageFlt            (Tablei_StorePageFlt),
    .Tablei_StoreAddreMis           (Tablei_StoreAddreMis),
    .Tableo_FULL                    (Tableo_FULL),
//------------------issue to access queue-----------------
    .ATUo_AQ_V                      (IFo_AQ_V),
    .ATUo_AQ_ID                     (IFo_AQ_ID),
    .ATUo_AQ_CMD                    (IFo_AQ_CMD),
    .ATUo_AQ_CI                     (IFo_AQ_CI),
    .ATUo_AQ_WT                     (IFo_AQ_WT),
    .ATUo_AQ_BSEL                   (IFo_AQ_BSEL),
    .ATUo_AQ_WDATA                  (IFo_AQ_WDATA),
    .ATUo_AQ_ADDR                   (IFo_AQ_ADDR),
    .ATUi_AQ_FULL                   (IFi_AQ_FULL),
//------------------------ATU FIB interface-------------------------
    .ATUo_FIB_WREN                  (ITLB_FIBo_WREN),
    .ATUo_FIB_REQ                   (ITLB_FIBo_REQ),
    .ATUi_FIB_ACK                   (ITLB_FIBi_ACK),
    .ATUi_FIB_FULL                  (ITLB_FIBi_FULL),
    .ATUo_FIB_ID                    (ITLB_FIBo_ID),
    .ATUo_FIB_CMD                   (ITLB_FIBo_CMD),
    .ATUo_FIB_BURST                 (ITLB_FIBo_BURST),
    .ATUo_FIB_SIZE                  (ITLB_FIBo_SIZE),
    .ATUo_FIB_ADDR                  (ITLB_FIBo_ADDR),
    .ATUo_FIB_DATA                  (ITLB_FIBo_DATA),
    .ATUi_FIB_ID                    (ITLB_FIBi_ID),
    .ATUi_FIB_RPL                   (ITLB_FIBi_RPL),
    .ATUi_FIB_V                     (ITLB_FIBi_V),
    .ATUi_FIB_DATA                  (ITLB_FIBi_DATA)
);
//-----------------------------Access Table-------------------------------
AccessTable             AccessTable(
    .GLB_CLKi                       (IFi_CLK),
    .GLB_SRSTi                      (IFi_ARST | IFi_GFlush | IFi_BFlush),
//------------------------Empty and FULL signals-----------------
    .Table_Full                     (Tableo_FULL),
    .Table_Empty                    (),             //Table为空信号不用
//-----------------------Access Table write port-----------------
    .Tablei_WREN                    (Tablei_WREN),
    .Tablei_WID                     (Tablei_WID),
    .Tablei_ADDR                    (Tablei_ADDR),
    .Tablei_PC                      (Tablei_PC),
    .Tablei_ITAG                    (Tablei_ITAG),
    .Tablei_priv                    (Tablei_priv),
    .Tablei_opcode                  (Tablei_opcode),
    .Tablei_opinfo                  (Tablei_opinfo),
    .Tablei_opsize                  (Tablei_opsize),
    .Tablei_ci                      (1'b0),
    .Tablei_InstPageFlt             (Tablei_InstPageFlt),
    .Tablei_LoadPageFlt             (Tablei_LoadPageFlt),
    .Tablei_StorePageFlt            (Tablei_StorePageFlt),
    .Tablei_InstAddrmis             (Tablei_InstAddrMis),
    .Tablei_LoadAddrMis             (Tablei_LoadAddrMis),
    .Tablei_StoreAddrMis            (Tablei_StoreAddreMis),
//--------------------Access Table read port----------------------
    .Tablei_RDEN                    (Tablei_RDEN),
    .Tablei_RID                     (Tablei_RID),
    .Tablei_Remove                  (Tablei_Remove),
    .Tableo_V                       (Tableo_V),
    .Tableo_ADDR                    (Tableo_ADDR),
    .Tableo_PC                      (Tableo_PC),
    .Tableo_ITAG                    (Tableo_ITAG),
    .Tableo_priv                    (Tableo_priv),
    .Tableo_opcode                  (Tableo_opcode),
    .Tableo_opinfo                  (Tableo_opinfo),
    .Tableo_opsize                  (Tableo_opsize),
    .Tableo_ci                      (),
    .Tableo_InstPageFlt             (Tableo_InstPageFlt),
    .Tableo_LoadPageFlt             (Tableo_LoadPageFlt),
    .Tableo_StorePageFlt            (Tableo_StorePageFlt),
    .Tableo_InstAddrmis             (Tableo_InstAddrmis),
    .Tableo_LoadAddrMis             (Tableo_LoadAddrMis),
    .Tableo_StoreAddrMis            (Tableo_StoreAddrMis)	
);
//         This result unit is used as instruction front, In this case, address offset is PC
ResultUnit#(.UsedAsInstrFront(1'b1))       
ResultUnit(
//---------------Global signal-----------
    .RUi_CLK                        (IFi_CLK),
    .RUi_ARST                       (IFi_ARST),
    .RUi_Flush                      (IFi_BFlush | IFi_GFlush),
//--------------Result Queue output------
    .RUi_RQ_V                       (IFi_RQ_V),
    .RUi_RQ_ID                      (IFi_RQ_ID),
    .RUi_RQ_WRERR                   (IFi_RQ_WRERR),
    .RUi_RQ_RDERR                   (IFi_RQ_RDERR),
    .RUi_RQ_RDY                     (IFi_RQ_RDY),
    .RUi_RQ_RDATA                   (IFi_RQ_RDATA),
    .RUo_RQ_ACK                     (IFo_RQ_ACK),
//---------------Access Table------------
    .Tablei_RDEN                    (Tablei_RDEN),
    .Tablei_RID                     (Tablei_RID),
    .Tablei_Remove                  (Tablei_Remove),
    .Tableo_V                       (Tableo_V),
    .Tableo_ADDR                    (Tableo_ADDR),
    .Tableo_PC                      (Tableo_PC),
    .Tableo_ITAG                    (Tableo_ITAG),
    .Tableo_priv                    (Tableo_priv),
    .Tableo_opcode                  (Tableo_opcode),
    .Tableo_opinfo                  (Tableo_opinfo),
    .Tableo_opsize                  (Tableo_opsize),
    .Tableo_ci                      (1'b0),
    .Tableo_InstPageFlt             (Tableo_InstPageFlt),
    .Tableo_LoadPageFlt             (Tableo_LoadPageFlt),
    .Tableo_StorePageFlt            (Tableo_StorePageFlt),
    .Tableo_InstAddrmis             (Tableo_InstAddrmis),
    .Tableo_LoadAddrMis             (Tableo_LoadAddrMis),
    .Tableo_StoreAddrMis            (Tableo_StoreAddrMis),	
//----------------Result output---------------
    .RUo_valid                      (PIP_IFo_MSC_valid),
    .RUo_InstPageFlt                (PIP_IFo_MSC_InstPageFlt),
    .RUo_InstAddrMis                (PIP_IFo_MSC_InstAddrMis),
    .RUo_InstAccFlt                 (PIP_IFo_MSC_InstAccFle),
    .RUo_LoadPageFlt                (),
    .RUo_LoadAddrMis                (),
    .RUo_LoadAccFlt                 (),
    .RUo_StorePageFlt               (),
    .RUo_StoreAddrMis               (),
    .RUo_StoreAccFlt                (),
    .RUo_ci                         (),
    .RUo_ITAG                       (),
    .RUo_priv                       (PIP_IFo_INFO_priv),
    .RUo_PC                         (PIP_IFo_INFO_pc),
    .RUo_VADDR                      (PIP_IFo_INFO_predictedPC),     //预测的PC值
    .RUo_DATA                       (PIP_IFo_DATA_instr),
    .RUi_ready                      (PIP_IFi_FC_ready)

);

endmodule

